﻿using System;
using System.Threading;

namespace Longbow.Cache
{
    /// <summary>
    /// 自动过期缓存项
    /// </summary>
    public class AutoExpireCacheEntry<T> : IDisposable
    {
        private Timer dispatcher;

        /// <summary>
        /// 获得 缓存值
        /// </summary>
        public T Value { get; }

        /// <summary>
        /// 获得 缓存对象存活时长 -1 表示永久缓存
        /// </summary>
        public int Period { get; }

        /// <summary>
        /// 获得/设置 缓存项描述信息
        /// </summary>
        public string Desc { get; set; }

        /// <summary>
        /// 获得 最后更新时间
        /// </summary>
        public DateTimeOffset CreateTime { get; private set; }

        /// <summary>
        /// 默认构造函数
        /// </summary>
        /// <param name="value">缓存对象</param>
        /// <param name="period">存活时长，单位毫秒</param>
        /// <param name="action">缓存过期回调函数</param>
        public AutoExpireCacheEntry(T value, int period, Action<T> action)
        {
            Period = value == null ? 50 : period;
            Value = value;
            CreateTime = DateTimeOffset.Now;
            if (period != -1)
            {
                // period = -1 表示永久缓存
                dispatcher = new Timer(o =>
                {
                    action(Value);
                }, null, period, Timeout.Infinite);
            }
        }

        /// <summary>
        /// 重置缓存时间方法
        /// </summary>
        public void Reset()
        {
            CreateTime = DateTimeOffset.Now;
            if (dispatcher != null) dispatcher.Change(Period, Timeout.Infinite);
        }

        #region Impletement IDispose
        /// <summary>
        /// Dispose 方法
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (dispatcher != null)
                {
                    dispatcher.Dispose();
                    dispatcher = null;
                }
            }
        }

        /// <summary>
        /// Dispose 方法
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        #endregion
    }
}
